#!/usr/bin/env python
# coding=utf-8

##############################################################################
#
# procsi.py : (feed, process, publish)
# A Pythonic Atom/RSS feeder and processor
#
# Copyright (c) 2007 Webcore Corp. All Rights Reserved.
#
##############################################################################
""" procsi.py - A Pythonic Atom/RSS feeder and processor

$Id$
"""

__author__  = 'Atsushi Shibata <shibata@webcore.co.jp>'
__docformat__ = 'plaintext'
__licence__ = 'MIT'

import os
import sys
from getopt import getopt
import logging

import yaml

from pluginmanager import FeederManager, ProcessorManager, PublisherManager
from utilities import nifty_formatter, nifty_input, dry_feed, dry_publish,\
                      exp2log
from config import *

def make_feedermanager(settings, plugindir='plugins'):
    """
    FeedManagerを作り，FeederPlugin, Feederインスタンスを作る
    
    settings  : 設定の辞書，IDをキーに，設定用の辞書をネストして指定する
    plugindir : プラグインを読み込む対象とするディレクトリ
    """
    feedermanager = FeederManager(plugindir, settings)
    return feedermanager

def make_publishermanager(settings, plugindir='plugins'):
    """
    PublisherManagerを作り，FeederPlugin, Feederインスタンスを作る
    
    settings  : 設定の辞書，IDをキーに，設定用の辞書をネストして指定する
    plugindir : プラグインを読み込む対象とするディレクトリ
    """
    publishermanager = PublisherManager(plugindir, settings)
    return publishermanager

def make_processormanager(settings, feeders, publishers, plugindir='plugins'):
    """
    ProcessorManagerを作り，FeederPlugin, Feederインスタンスを作る
    
    settings  : 設定の辞書，IDをキーに，設定用の辞書をネストして指定する
    plugindir : プラグインを読み込む対象とするディレクトリ
    """
    processormanager = ProcessorManager(plugindir, settings,
                                            feeders, publishers)
    return processormanager

def handle_option(opts, feedermanager, publishermanager):
    """
    オプションを処理する
    """
    for option, value in opts:
        if option == '--test':
            # プラグインIDを指定してテストを実施
            if value in feedermanager:
                print """==== Testing Feeder plugin '%s:%s' ====""" % \
                            (value, type(feedermanager[value]))
                dry_feed(value, feedermanager)
                sys.exit()
            elif value in publishermanager:
                print """==== Testing Publisher plugin '%s:%s' ====""" % \
                            (value, type(publishermanager[value]))
                dry_publish(value, publishermanager)
                sys.exit()
            else:
                print """Error : Plugin '%s' not found.""" % value

def config_log(opts):
    """
    引数のログレベルを設定する
    """
    from config import log_format, log_datefmt, log_filename, log_filemode
    log_level = logging.INFO
    for option, value in opts:
        if option == '--loglevel':
            if value.lower() == 'info':
                log_level = logging.INFO
            elif value.lower() == 'debug':
                log_level =  logging.DEBUG
            elif value.lower() == 'error':
                log_level =  logging.ERROR
    log_filename = os.path.join(os.path.dirname(__file__), log_filename)
    if '--test' in [x[0] for x in opts]:
        log_filename = None
        log_filemode = None
        log_level = logging.ERROR
    logging.basicConfig(level=log_level, format=log_format,
                        datefmt=log_datefmt, filename=log_filename,
                        filemode=log_filemode)


def main():
    try:
        # import用のpathを追加する
        sys.path.append(os.path.dirname(__file__))

        opts, rest = getopt(sys.argv[1:], '', long_options)

        # ログの設定
        config_log(opts)

        logging.debug("Start procsi")

        # 設定を読み込む
        settingfile = os.path.join(
                    os.path.dirname(__file__), settingbase, settingfilename)
        d = yaml.load(open(settingfile).read())

        # feeder, publisher, processroを作る
        feedermanager = make_feedermanager(d['feeders'])
        publishermanager = make_publishermanager(d['publishers'])
        processormanager = make_processormanager(d['processors'],
                                        feedermanager, publishermanager)

        if opts:
            handle_option(opts, feedermanager, publishermanager)

        # 設定にしたがってprocess
        for p in processormanager:
            processormanager.process(p, feedermanager, publishermanager)

        logging.debug("End procsi")
    except SystemExit:
        pass
    except:
        exp2log(logging.fatal)

if __name__ == '__main__':
    main()